<script setup>
import { ref, onMounted, computed } from 'vue'
import { sessionApi, pageFilesApi, updNameApi, updTypeApi, delFilesApi, selDictsApi, oneFileApi } from '@/commons/api'
import routes from '@/commons/router'
import Msg from '@/components/message'
import Confirm from '@/components/confirm'
import Pager from '@/components/pager/Pager.vue'
import { formatDate } from '@/commons/filter'
import TreeSel from '@/components/cascader/TreeSel.vue'
import Selector from '@/components/select/Selector.vue'
import axios from 'axios'
import noPic from '@/assets/img/7.svg'
import {CScrollbar} from 'c-scrollbar'
import Loader from '@/components/loader/Loader.vue'

const loadShow = ref(false)

// 界面挂载前处理
onMounted(() => {
  // 获取用户会话信息
  checkAuth()
})

const myAuth = ref({
  saveAuth: false,
  procAuth: false
})
// checkAuth 获取权限
const checkAuth = async () => {
  loadShow.value = true
  try {
    const res = await sessionApi()
    if (res.code === import.meta.env.VITE_SUCCESS_CODE) {
      const userBtnCode = res.data.btnCodes
      myAuth.value = {
        saveAuth: userBtnCode.indexOf('1001011101') !== -1,
        procAuth: userBtnCode.indexOf('1001011102') !== -1
      }
      await list(0, 1)
      await selType()
    } else {
      localStorage.removeItem("token")
      Msg({ kind: 'error', txt: res.msg })
      routes.replace('/login')
    }
    loadShow.value = false
  } catch (e) {
    loadShow.value = false
    Msg({ kind: 'error', txt: '系统错误，请联系管理员！' + e })
  }
}

const schObj = {
  keywords: '',
  fileType: '',
  typeName: '',
  typeCode: '',
  kind: 0,
  kindName: '',
  kindCode: '',
  beginTime: 0,
  endTime: 0,
  offset: 0,
  limit: 28
}
const kindList = ref([
  {selId: 1, selName: '图片', selCode: '101', chked: false},
  {selId: 2, selName: '文档', selCode: '102', chked: false},
  {selId: 3, selName: '压缩包', selCode: '103', chked: false},
  {selId: 4, selName: '音视频', selCode: '104', chked: false},
  {selId: 5, selName: '其它', selCode: '105', chked: false}
])
const schRef = ref(schObj)
const total = ref(0)
const curPage = ref(1)
const fileList = ref([])
const hasData = ref(false)
const checkList = ref([])
// list 列表展示
const list = async (offset, cur) => {
  schRef.value.offset = offset || 0
  curPage.value = cur || 1
  hasData.value = false
  const res = await pageFilesApi(schRef.value)
  if(res.code === import.meta.env.VITE_SUCCESS_CODE && res.data) {
    hasData.value = true
    total.value = res.data.total
    fileList.value = res.data.list
    idList.value = []
    checkList.value = []
    allCheck.value = false
    res.data.list.forEach(() => {
      checkList.value.push(false)
    })
  }
}

// search 筛选
const schShow = ref(false)
const search = () => {
  schShow.value = !schShow.value
}

// clrSch 重置搜索框
const clrSch = () => {
  schRef.value = {
    keywords: '',
    fileType: '',
    typeName: '',
    typeCode: '',
    kind: 0,
    kindName: '',
    kindCode: '',
    beginTime: 0,
    endTime: 0,
    offset: 0,
    limit: 28
  }
  list(0, 1)
}

// 选择效果实现
const idList = ref([])
const allCheck = ref(false)
// checkAll 全选
const checkAll = () => {
  idList.value = []
  checkList.value = []
  allCheck.value = !allCheck.value
  if(allCheck.value) {
    fileList.value.forEach(item => {
      idList.value.push(item.fileId)
      checkList.value.push(true)
    })
  } else {
    fileList.value.forEach(() => {
      checkList.value.push(false)
    })
  }
}
// checkCurId 单选
const checkCurId = (idx, fileId) => {
  if(!checkList.value[idx]) {
    idList.value.push(fileId)
  } else {
    idList.value.splice(idList.value.findIndex(id => id === fileId), 1)
  }
  checkList.value[idx] = !checkList.value[idx]
}

const fileObj = {
  fileIds: '',
  fileType: '',
  typeName: '',
  fileId: '',
  fileName: ''
}
const fileForm = ref(fileObj)
// updType 批量修改分类
const modalShow1 = ref(false)
const modalShow2 = ref(false)
const modalShow3 = ref(false)
const updType = () => {
  if(idList.value.length > 0) {
    modalShow1.value = true
  } else {
    Msg({ kind: 'warn', txt: '请至少选择一项进行修改！' })
  }
}

// updTypeProc 修改分类提交提交
const updTypeProc = async () => {
  let fileIds = idList.value.join(",")
  let fileType = fileForm.value.fileType
  if(fileIds === '' || fileIds.length < 21) {
    Msg({ kind: 'warn', txt: '请至少选择一项进行修改！' })
    return
  } else if(fileType === '' || fileType.length !== 21) {
    Msg({ kind: 'warn', txt: '请选择要迁移到的分类！' })
    return
  }
  fileForm.value.fileIds = fileIds
  loadShow.value = true
  try {
    const res = await updTypeApi(fileForm.value)
    if(res.code === import.meta.env.VITE_SUCCESS_CODE) {
      closeModal(1)
      await list(0, 1)
      Msg({ kind: 'success', txt: '恭喜您，文件分类修改成功！' })
    } else {
      Msg({ kind: 'error', txt: res.msg })
    }
    loadShow.value = false
  } catch (e) {
    loadShow.value = false
    Msg({ kind: 'error', txt: '系统错误，请联系管理员！' + e })
  }
}

// updName 修改名称
const updName = (fileId, fileName) => {
  modalShow2.value = true
  fileForm.value.fileId = fileId
  fileForm.value.fileName = fileName
}

// updNameProc 修改文件名称提交
const updNameProc = async () => {
  let fileId = fileForm.value.fileId
  let fileName = fileForm.value.fileName
  if(fileId === '' || fileId.length !== 21) {
    Msg({ kind: 'warn', txt: '文件编号不能为空！' })
    return
  } else if(fileName === '' || fileName.length ===0 || fileName.length > 85) {
    Msg({ kind: 'warn', txt: '文件名称不能为空，且不超过80个字符！' })
    return
  }
  loadShow.value = true
  try {
    const res = await updNameApi(fileForm.value)
    if(res.code === import.meta.env.VITE_SUCCESS_CODE) {
      closeModal(2)
      await list(0, 1)
      Msg({ kind: 'success', txt: '恭喜您，文件名称修改成功！' })
    } else {
      Msg({ kind: 'error', txt: res.msg })
    }
    loadShow.value = false
  } catch (e) {
    loadShow.value = false
    Msg({ kind: 'error', txt: '系统错误，请联系管理员！' + e })
  }
}

// closeModal 关闭弹出层，并重置表单数据
const closeModal = (kind) => {
  switch(kind) {
    case 1:
      modalShow1.value = false
      fileForm.value.fileType = ''
      fileForm.value.typeName = ''
      fileForm.value.typeCode = ''
      break;
    case 2:
      modalShow2.value = false
      fileForm.value.fileId = ''
      fileForm.value.fileName = ''
      break;
    case 3:
      modalShow3.value = false
      break;
  }
}

// deletes 删除文件
const deletes = async() => {
  if(!idList || idList.value.length===0) {
    Msg({ kind: 'warn', txt: '请至少选择一项再操作！' })
    return
  }
  Confirm('确定要删除选中的文件吗？').then(() => {
    delFiles()
  }).catch(() => {
    Msg({ kind: 'info', txt: "取消处理选中的数据！" })
  })
}
// delFiles 删除文件实现，分离出来防止调用时异步报错
const delFiles = async () => {
  let fileIds = idList.value.join(',')
  loadShow.value = true
  try {
    const res = await delFilesApi({ fileIds })
    if(res.code === import.meta.env.VITE_SUCCESS_CODE) {
      await list(0, 1)
      Msg({ kind: 'success', txt: '恭喜您，文件信息删除成功！' })
    } else {
      Msg({ kind: 'error', txt: res.msg })
    }
    loadShow.value = false
  } catch (e) {
    loadShow.value = false
    Msg({ kind: 'error', txt: '系统错误，请联系管理员！' + e })
  }
}

// fmtDate 时间戳转时间
const fmtDate = computed(() => {
  return (time, kind) => {
    let date = new Date(time*1000)
    return formatDate(date, kind)
  }
})

// selType 获取分类下拉列表
const typeList = ref([])
const selType = async () => {
  const res = await selDictsApi({kind: 2, typeCode: 'SYS_FILE'})
  if(res.code === import.meta.env.VITE_SUCCESS_CODE) {
    typeList.value = res.data
  }
}

const setValue = (item, kind) => {
  switch(kind) {
    case 1:
      schRef.value.fileType = item.selId
      schRef.value.typeName = item.selName
      schRef.value.typeCode = item.selCode
      break
    case 2:
      fileForm.value.fileType = item.selId
      fileForm.value.typeName = item.selName
      fileForm.value.typeCode = item.selCode
      break
    case 3:
      schRef.value.kind = item.selId
      schRef.value.kindName = item.selName
      schRef.value.kindCode = item.selCode
      break
  }
}

// detailFile 查看文件详情
const fileRef = ref()
const detailFile = async (fileId) => {
  const res = await oneFileApi({fileId})
  if(res.code === import.meta.env.VITE_SUCCESS_CODE) {
    modalShow3.value = true
    fileRef.value = res.data
  } else {
    Msg({ kind: 'error', txt: res.msg })
  }
}

// download 下载文件
const download = async (fileId) => {
  loadShow.value = true
  axios.post('http://exam-api.haobing.pw/system/file/download', {fileId}, {
  // axios.post('http://127.0.0.1:8101/system/file/download', {fileId}, {
    headers: {'token': localStorage.getItem("token")},
    responseType: 'blob'
  }).then(res => {
    let aTag = document.createElement("a")
    aTag.href = window.URL.createObjectURL(new Blob([res.data]))
    aTag.download = decodeURI(res.headers['content-disposition'].split('=')[1].replace(' ', ''))
    aTag.click()
    window.URL.revokeObjectURL(aTag.href)
    loadShow.value = false
  }).catch(function (err) {
    loadShow.value = false
    Msg({kind: 'error', txt: err})
  })
}
</script>

<template>
  <div class="file-a">
    <div class="file-b">
      <div class="file-c">
        <div class="file-d" @click="checkAll()" title="全选"><i :class="['iconfont', allCheck ? 'chked' : 'chk']" v-html="allCheck ? '&#xea3a;' : '&#xea46;'" /></div>
        <div v-if="myAuth.saveAuth" class="btn-pi mr15" title="迁移" @click="updType"><i class="iconfont">&#xea31;</i> 归类</div>
        <div v-if="myAuth.procAuth" class="btn-de mr15" title="删除" @click="deletes"><i class="iconfont">&#xea45;</i> 删除</div>
        <div class="btn-r mr15" title="筛选" @click="search"><i class="iconfont">&#xea49;</i></div>
        <div class="btn-r mr15" title="刷新" @click="list(0, 1)"><i class="iconfont">&#xea8c;</i></div>
      </div>
      <div class="file-e"><i class="iconfont">&#xeaaa;</i> 当前位置：工作台 > 系统管理 > 文件管理</div>
    </div>
    <div v-show="schShow" class="file-f">
      <div class="mr15 mt10"><tree-sel :kind="1" :tree-list="typeList" :inboxed="true" :curName="schRef.typeName!=='' ? schRef.typeName+'['+schRef.typeCode+']' : ''" pre-name="分类" @setValue="setValue" /></div>
      <div class="mr15 mt10"><selector :kind="3" :sel-list="kindList" :inboxed="true" :curName="schRef.kindName!=='' ? schRef.kindName+'['+schRef.kindCode+']' : ''" pre-name="种类" @setValue="setValue" /></div>
      <div class="mr15 mt10"><input type="text" v-model="schRef.keywords" maxlength="30" placeholder="请输入关键字" class="sch-ipt" /></div>
      <div class="file-g mt10">
        <div class="btn-pi mr15" title="搜索" @click="list(0, 1)"><i class="iconfont">&#xea8e;</i> 搜索</div>
        <div class="btn-d" title="重置" @click="clrSch"><i class="iconfont">&#xea4f;</i> 重置</div>
      </div>
    </div>
    <div v-if="hasData">
      <div class="file-h">
        <div class="file-i" v-for="(curFile, index) in fileList" :key="curFile.fileId">
          <div class="file-j" @click="detailFile(curFile.fileId)"><img :alt="curFile.fileName+curFile.fileExt" v-lazy="curFile.kind===1 ? curFile.visitUrl.replace('/img/', '/img/thumb/') : noPic" class="max-img" /></div>
          <div class="file-k">{{curFile.fileName}}</div>
          <div class="file-l">
            <div class="file-m"><i @click="checkCurId(index, curFile.fileId)" :class="['iconfont', checkList[index]  ? 'chked' : 'chk']" v-html="checkList[index]  ? '&#xe685;' : '&#xe686;'"></i></div>
            <div v-if="myAuth.saveAuth" class="file-m"><span class="cl-warn" title="修改文件名称" @click="updName(curFile.fileId, curFile.fileName)"><i class="iconfont">&#xea48;</i> 改名</span></div>
          </div>
        </div>
      </div>
      <Pager v-if="hasData" :limit="schRef.limit" :total="total" :page="curPage" @turn="list" />
    </div>
    <div v-else class="no-data">暂无内容</div>

    <!-- 新增、修改弹出层 -->
    <transition name="fade-mod" appear>
      <div v-if="modalShow1" class="modal-backdrop">
        <c-scrollbar>
          <div class="modal" style="width: 400px;">
            <div class="modal-header">
              <div class="header-left"><i class="iconfont">&#xea54;</i> 修改文件分类</div>
              <div class="header-right" @click="closeModal(1)"><i class="iconfont fs22">&#xea7f;</i></div>
            </div>
            <div class="modal-body">
              <div>
                <div class="ipt-title"><span class="required">*</span>文件分类</div>
                <tree-sel :tree-list="typeList" :kind="2" :inboxed="false" :curName="fileForm.typeName ? fileForm.typeName+'['+fileForm.typeCode+']' : ''" pre-name="所属分类" @setValue="setValue" />
              </div>
            </div>
            <div class="modal-footer">
              <div class="btn-pi mr15" @click="updTypeProc"><i class="iconfont">&#xea90;</i> 保存</div>
              <div class="btn-d" @click="closeModal(1)"><i class="iconfont">&#xea4f;</i> 取消</div>
            </div>
          </div>
        </c-scrollbar>
      </div>
    </transition>

    <!-- 新增、修改弹出层 -->
    <transition name="fade-mod" appear>
      <div v-if="modalShow2" class="modal-backdrop">
        <c-scrollbar>
          <div class="modal" style="width: 800px;">
            <div class="modal-header">
              <div class="header-left"><i class="iconfont">&#xea54;</i> 修改文件名称</div>
              <div class="header-right" @click="closeModal(2)"><i class="iconfont fs22">&#xea7f;</i></div>
            </div>
            <div class="modal-body">
              <div>
                <div class="ipt-title"><span class="required">*</span>文件名称</div>
                <div><input type="text" v-model="fileForm.fileName" placeholder="请选输入文件名称" class="ipt" /></div>
              </div>
            </div>
            <div class="modal-footer">
              <div class="btn-pi mr15" @click="updNameProc"><i class="iconfont">&#xea90;</i> 保存</div>
              <div class="btn-d" @click="closeModal(2)"><i class="iconfont">&#xea4f;</i> 取消</div>
            </div>
          </div>
        </c-scrollbar>
      </div>
    </transition>

    <!-- 新增、修改弹出层 -->
    <transition name="fade-mod" appear>
      <div v-if="modalShow3" class="modal-backdrop">
        <c-scrollbar>
          <div class="modal" style="width: 1100px;">
            <div class="modal-header">
              <div class="header-left"><i class="iconfont">&#xea54;</i> 查看文件详情</div>
              <div class="header-right" @click="closeModal(3)"><i class="iconfont fs22">&#xea7f;</i></div>
            </div>
            <div class="modal-body">
              <div class="file-n">
                <div class="file-o">
                  <div class="ipt-title">文件名称</div>
                  <div class="file-p">{{fileRef.fileName}}{{fileRef.fileExt}}</div>
                </div>
                <div class="file-o">
                  <div class="ipt-title">文件大小</div>
                  <div class="file-p">{{parseInt(parseInt(fileRef.fileSize)/1024)}}kb</div>
                </div>
                <div class="file-o">
                  <div class="ipt-title">文件分类</div>
                  <div class="file-p">{{fileRef.dictName}}[{{fileRef.dictCode}}]</div>
                </div>
                <div class="file-o">
                  <div class="ipt-title">上传时间</div>
                  <div class="file-p">{{fmtDate(fileRef.addTime, 2)}}</div>
                </div>
              </div>
              <div v-if="fileRef.kind===1" class="file-q"><img :alt="fileRef.fileName" v-lazy="fileRef.visitUrl" class="max-img" /></div>
              <div v-else class="btn-p" @click="download(fileRef.fileId)">下载</div>
            </div>
            <div class="modal-footer">
              <div class="btn-pi mr15" @click="updNameProc"><i class="iconfont">&#xea90;</i> 保存</div>
              <div class="btn-d" @click="closeModal(3)"><i class="iconfont">&#xea4f;</i> 取消</div>
            </div>
          </div>
        </c-scrollbar>
      </div>
    </transition>
    <loader :loadShow="loadShow" />
  </div>
</template>

<style scoped>
.file-a {padding: 10px;}
.file-b {padding: 0 20px 10px 20px; display: flex; display: -webkit-flex;}
.file-c {display: inline-flex; display: -webkit-inline-flex;}
.file-d {padding: 5px 15px 0 0;}
.file-e {flex-grow: 1; text-align: right; padding-top: 10px; color: #666;}
.file-f {border: 1px dashed #DDD; padding: 5px 15px 15px 15px; display: flex; display: -webkit-flex; flex-wrap: wrap; margin-bottom: 10px;}
.file-g {display: inline-flex; display: -webkit-inline-flex;}
.file-h {display: flex; display: -webkit-flex; flex-wrap: wrap; padding: 5px;}
.file-i {width: 154px; height: 214px; border: 1px #EBEBEB solid; padding: 0 5px; margin: 5px;}
.file-i:hover {box-shadow: #CCC 0 0 5px;}
.file-j {width: 150px; height: 150px; overflow: hidden; padding: 2px; text-align: center; cursor: pointer; display: flex; align-items: center; justify-content: center;}
.file-k {height: 30px; text-align: center;}
.file-l {text-align: center; display: inline-flex; display: -webkit-inline-flex; justify-content: space-around; flex-direction: row;}
.file-m {width: 60px;}
.file-n {display: flex; display: -webkit-flex; flex-wrap: wrap; padding:20px;}
.file-o {width: 50%;}
.file-p {padding: 5px 20px;}
.file-q {border: 1px solid #CCC; padding: 4px; text-align: center;}
</style>